<template>
  <m-window-frame
    style="height: 100%"
    title="规则管理"
    :okLoading="saveLoading"
    class="v-rule-manage"
    @cancel="handleCancel"
    @ok="handleSave"
  >
    <attr-tips type="validateRuleManage"></attr-tips>
    <div class="__content">
      <el-tree
        ref="treeRef"
        :data="treeData"
        node-key="instanceId"
        :default-expanded-keys="expandedKeys"
        :default-checked-keys="defaultCheckedKeys"
        :expand-on-click-node="false"
        show-checkbox
        @node-expand="handleNodeExpand"
        @node-collapse="handleNodeCollapse"
      >
        <template #default="{ node, data }">
          <span class="custom-tree-node">
            <span
              class="tree_node"
              :class="{ _selected: selectedNode?.instanceId === data.instanceId && selectedNode?.ownerId }"
              @click.stop="handleNodeClick(data)"
            >
              <span class="v-tree-text">
                <img
                  :src="data.icon"
                  class="_tree-node-icon"
                />
                <span
                  class="text"
                  :title="data.instanceName"
                  style="flex: 1; overflow: hidden; text-overflow: ellipsis"
                >
                  {{ data.instanceName }}
                </span>
              </span>
              <span
                v-if="
                  data.appliedStereotypes && data.appliedStereotypes[0] === StType['Customization::ValidationRule'] && data.isInteractive
                "
                class="hover-icon"
                style="flex-shrink: 0; opacity: 0; transition: opacity 0.2s"
              >
                <el-icon
                  class="g-m-r-10"
                  @click="handleEdit(data)"
                >
                  <Edit />
                </el-icon>
                <el-icon @click="handleDelete(data.instanceId)">
                  <Delete />
                </el-icon>
              </span>
            </span>
          </span>
        </template>
      </el-tree>
    </div>
    <template #footer-left>
      <el-button
        type="primary"
        @click="handleAdd"
      >
        <el-icon><Plus /></el-icon>
        {{ $t("新增校验规则") }}
      </el-button>
    </template>
  </m-window-frame>
</template>
<script lang="ts" setup>
import { MWindowFrame, modelService, ipcWindowUtil, MTreeNode, confirmWindow, validateRuleUpdateWindow, ApiCode, StType, MetaclassType, locale, AttrTips, removeNodeById, flattenTree, initTree } from "@/mdesign-lib/mdesign-app.umd.js";
import { Edit, Delete, Plus } from "@element-plus/icons";
import { ref, onMounted } from "vue";
import { ElTree } from "element-plus";
import { WindowName } from "@/mdesign-lib/mdesign-main.js";

interface ValidationRuleModelVo {
  instanceId: string;
  instanceName: string;
  icon: string;
  children: ValidationRuleModelVo[];
  appliedStereotypes: string[];
  isInteractive: boolean;
  metaClass: string;
  qualifiedName: string;
  ownerId: string;
  isElementImport?: boolean;
  disabled?: boolean;
}

const query = app.$route.query;
const saveLoading = ref<boolean>(false);
const treeData = ref<ValidationRuleModelVo[]>([]);
const expandedKeys = ref<string[]>([]);
const defaultCheckedKeys = ref<string[]>([]);
const treeRef = ref();
const ruleDatas = ref<any[]>([]);
const ruleAndGroupDatas = ref<any[]>([]);
const importRuleDatas = ref<any[]>([]);
const addModelId = ref<string>();

const selectedNode = ref<ValidationRuleModelVo>();
const savedExpandedKeys = ref<string[]>([]);

onMounted(async () => {
  await getRuleByGroupId();
  loadData();
});

/**
 * 节点点击事件
 * @param node 选中的节点
 */
const handleNodeClick = (node: ValidationRuleModelVo) => {
  selectedNode.value = node;
};

function handleNodeExpand(data: ValidationRuleModelVo) {
  if (!expandedKeys.value.includes(data.instanceId)) {
    expandedKeys.value.push(data.instanceId);
    savedExpandedKeys.value = expandedKeys.value;
  }
}

function handleNodeCollapse(data: ValidationRuleModelVo) {
  const index = expandedKeys.value.indexOf(data.instanceId);
  if (index !== -1) {
    expandedKeys.value.splice(index, 1);
    savedExpandedKeys.value = expandedKeys.value;
  }
}

/**
 * 加载校验规则树数据
 */
async function loadData(modelId?: string) {
  const data = await modelService.queryValidationModelTree(query.projectId as string);
  if (data) {
    const ruleMap = new Map<string, any>();
    ruleDatas.value.forEach(item => {
      ruleMap.set(item.instanceId, item);
    });
    treeData.value = initTree([data], {
      customFn: (node: ValidationRuleModelVo, nodeOld: any) => {
        const ruleInfo = ruleMap.get(nodeOld.instanceId);
        if (ruleInfo) {
          node.disabled = !ruleInfo.isElementImport; // 导入的关系可取消勾选，原有的规则不能取消勾选
          node.isElementImport = !!ruleInfo.isElementImport;
        }
        if (
          ((!nodeOld.children || nodeOld.children.length === 0) && nodeOld.metaClass === MetaclassType.Package) ||
          nodeOld.instanceId === modelId
        ) {
          node.disabled = true;
        }
        node.instanceId = nodeOld.instanceId;
        node.instanceName = nodeOld.instanceName;
        node.icon = modelService.getModelIcon(query.projectId as string, nodeOld.icon);
        node.appliedStereotypes = nodeOld.appliedStereotypes;
        node.isInteractive = nodeOld.isInteractive;
        node.metaClass = nodeOld.metaClass;
        node.qualifiedName = nodeOld.qualifiedName;
        node.ownerId = nodeOld.ownerId;
      }
    }) as ValidationRuleModelVo[];

    // 如果有保存的展开状态，则使用保存的状态，否则使用默认展开根节点
    if (savedExpandedKeys.value.length > 0) {
      expandedKeys.value = savedExpandedKeys.value;
      savedExpandedKeys.value = [];
    } else {
      expandedKeys.value = [data.instanceId];
    }
  }
}

/**
 * 获取分组下的校验规则，并设置默认勾选和置灰
 */
const getRuleByGroupId = async () => {
  const data = await modelService.queryValidationModelsOfValidationGroup({
    projectId: query.projectId as string,
    validationGroupInstanceId: query.groupId as string
  });
  ruleAndGroupDatas.value = flattenTree(data);

  ruleDatas.value = ruleAndGroupDatas.value.filter(item => item.appliedStereotypes[0] === StType["Customization::ValidationRule"]);
  const importRuleIds = ruleDatas.value.filter(item => item.isElementImport === true).map(item => item.instanceId);
  const localRuleIds = ruleDatas.value.filter(item => item.isElementImport === false).map(item => item.instanceId);
  // 通过关系导入的规则
  importRuleDatas.value = ruleDatas.value.filter(item => item.isElementImport === true);
  defaultCheckedKeys.value = [...importRuleIds, ...localRuleIds];
};

/**
 * 删除校验规则
 * @param id 规则id
 */
const handleDelete = async (id: string) => {
  const res = await confirmWindow.popup({
    title: locale.t("警告"),
    content: locale.t(`确认删除此校验规则吗?`),
    status: "warn"
  });
  if (res.success) {
    const result = await modelService.removeModel(query.projectId as string, [id]);
    if (result && result.code == ApiCode.SUCCESS) {
      removeNodeById(treeData.value, id, "instanceId");
      app.$notify({
        type: "success",
        title: locale.t("提示"),
        message: locale.t("删除成功")
      });
    }
    return;
  }
};

/**
 * 编辑校验规则
 * @param node 规则节点
 */
const handleEdit = async (node: MTreeNode) => {
  validateRuleUpdateWindow
    .popup({
      projectId: query.projectId as string,
      id: node.instanceId,
      groupId: query.groupId as string,
      groupName: query.groupName as string
    })
    .then(res => {
      if (res.success) {
        app.$notify({
          type: "success",
          title: locale.t("提示"),
          message: locale.t("修改校验规则成功")
        });
        loadData();
      }
    });
};

async function handleSave() {
  try {
    saveLoading.value = true;
    const checkedNodes = treeRef.value?.getCheckedNodes() || [];
    const checkedRules = checkedNodes.filter(
      node => node.appliedStereotypes.includes(StType["Customization::ValidationRule"]) && node.disabled !== true
    );
    // if (!checkedRules.length) {
    //   return app.$notify({
    //     type: "warning",
    //     title: locale.t("提示"),
    //     message: locale.t("请选择校验规则！")
    //   });
    // }
    const instanceIds = checkedRules.map(node => node.instanceId);
    // 计算需要删除和新增的规则ID
    const deleteRules = importRuleDatas.value.filter(item => !instanceIds.includes(item.instanceId));
    // 待删除的id数组
    const deleteRuleIds = deleteRules.flatMap(rule => rule.elementImportRelationShipIds || []);
    // 新增的规则
    const createRules = checkedNodes.filter(
      node => node.appliedStereotypes.includes(StType["Customization::ValidationRule"]) && node.disabled !== true && !node.isElementImport
    );
    // 删除已导入的关系
    if (deleteRuleIds.length > 0) {
      try {
        await modelService.removeModel(query.projectId as string, deleteRuleIds);
      } catch (err) {
        app.$notify({
          type: "error",
          title: locale.t("错误"),
          message: locale.t("删除关系失败")
        });
        throw err;
      }
    }
    // 新增导入关系
    const needCreateRules = createRules.filter(rule => rule.instanceId !== addModelId.value);
    if (needCreateRules.length > 0) {
      await modelService.batchCreate({
        applyStereotypes: [],
        projectId: query.projectId as string,
        metaclass: MetaclassType.ElementImport,
        source: query.groupId as string,
        targets: needCreateRules.map(item => item.instanceId),
        type: 1
      });
    }
    ipcWindowUtil.closeWindow({ WindowName: WindowName.RuleManagerWindow, success: true });
  } catch (error) {
    console.error("保存规则失败:", error);
  } finally {
    saveLoading.value = false;
  }
}

const handleAdd = () => {
  validateRuleUpdateWindow
    .popup({
      projectId: query.projectId as string,
      groupId: query.groupId as string,
      groupName: query.groupName as string
    })
    .then(res => {
      if (res.success) {
        app.$notify({
          type: "success",
          title: locale.t("提示"),
          message: locale.t("新增校验规则成功")
        });
        if (res.modelId) {
          addModelId.value = res.modelId;
          loadData(res.modelId);
          defaultCheckedKeys.value.push(res.modelId);
        }
      }
    });
};

function handleCancel() {
  ipcWindowUtil.closeWindow({ success: false });
}
</script>
<style lang="scss">
.v-rule-manage {
  width: 100%;
  height: 100%;
  .__content {
    height: calc(100% - 50px);
    overflow-y: auto;
    padding: 10px;
    .custom-tree-node {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 14px;
      padding-right: 8px;
      width: 100%;
      overflow-x: hidden;
      ._tree-node-icon {
        position: relative;
        width: 16px;
        height: 16px;
      }
      .tree_node {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        .v-tree-text {
          width: calc(100% - 20px);
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
        .text {
          padding: 0 5px;
        }
        &:hover .hover-icon {
          opacity: 1 !important;
        }
      }
    }
  }
}
</style>
